# coding=utf-8
import re, uuid, shortuuid, string, json
from flask import Blueprint, request, jsonify, session
from random import randint
from utils import restful
from utils.redis import Redis
from form.user import LoginForm
from model import User, FollowTable
from exts import db, cache
from setting import UserKey
from decorator import login_required
from setting import Prefixs
from .common import queryUserCache
from datetime import datetime

bp = Blueprint('user', __name__, url_prefix='/user')


@bp.route('/<int:id>')
def queryuser(id):
    user = User.query.get(id)
    if not user:
        return restful.fail("用户不存在！"), 404
    return restful.success(data=user.to_dict())


@bp.route("/code", methods=["GET", "POST"])
def sendCode():
    pattern = r'^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$'
    phone = request.args.get("phone")
    if not re.match(pattern, phone):
        return restful.fail()
    code = str(randint(1000, 9999))
    key = Prefixs.login_captcha_prefix + phone
    cache.set(key, code, 60 * 5)
    print("验证码：", code)
    return restful.success(data=code)


@bp.route("/me", methods=["GET", "POST"])
@login_required
def me():
    token_key = Prefixs.user_token_prefix + request.headers.get("Authorization")
    user = Redis.hgetall(token_key)
    # print(user)
    if not user:
        return restful.fail()
    return restful.success(data=user)


@bp.route("/info/<id>", methods=["GET", "POST"])
@login_required
def info(id):
    user_info = User.query.get(id).to_dict()
    # print(user_info)
    if not user_info:
        return restful.fail()
    return restful.success(data=user_info)


@bp.route("/login", methods=["POST"])
def login():
    form = LoginForm(data=request.json)
    # print(request.json)
    # print(form.data)
    if not form.validate():
        return restful.fail()
    phone_number = form.phone.data
    code = form.code.data
    key = Prefixs.login_captcha_prefix + phone_number
    captcha = cache.get(key)
    if not captcha or captcha != code:
        print("验证码不存在！")
        return restful.fail("验证码不存在!")
    # if phone_number not in session or session[phone_number] != code:
    #     error_message = "验证码不存在！"
    #     print(error_message)
    #     return restful.fail(message=error_message)
    # 如果没有用户就创建新用户
    user = User.query.filter_by(phone=phone_number).first()
    if not user:
        char_list = "0123456789" + string.ascii_letters
        # 自定义位数
        nick_name = Prefixs.userID_prefix + shortuuid.ShortUUID(alphabet=char_list).random(length=10)
        user = User(phone=phone_number, password="", nick_name=nick_name, icon="")
        db.session.add(user)
        db.session.commit()
    # 登录时将用户信息放到session中
    token = str(uuid.uuid4()).replace('-', '')
    token_key = Prefixs.user_token_prefix + token
    user = user.to_dict()
    # # 替换为token-session取代session[UserKey] = user
    Redis.hmset(token_key, {key: user[key] for key in ["id", "nick_name", "icon"]})  # 只存储部分字段
    Redis.expire(token_key, 60 * 60)
    # print(Redis.hgetall(token_key))
    # 登录时清除短信验证码缓存
    key = Prefixs.login_captcha_prefix + phone_number
    cache.delete(key)
    # 登录时吧所有关注信息放到redis中
    follow_info = db.session.query(FollowTable.follow_user_id).filter_by(user_id=user['id']).all()
    follow_info = [item[0] for item in follow_info]
    key = Prefixs.follow_user_set_prefix + str(user['id'])
    if follow_info:
        Redis.sadd(key, *follow_info)
        Redis.expire(key, 3600 * 24)
    return restful.success(data=token)


@bp.route("/logout", methods=["POST"])
def logout():
    return restful.success()

# 签到，页面没有实现
@bp.route("/sign")
def user_sign():
    # 获取当前用户信息
    user_info = queryUserCache()
    # 获取日期
    date = datetime.now()
    # 拼接key
    key = Prefixs.user_sign_key + date.strftime("%Y:%m:") + user_info['id']
    # 获取天数
    day = date.day
    # 写入redis,bitmap下标从0开始，需要减一
    Redis.setbit(key, day - 1, 1)
    return restful.success()

# 统计最近签到次数，页面没有实现
@bp.route("/sign/count")
def sign_count():
    # 获取当前用户信息
    user_info = queryUserCache()
    # 获取日期
    date = datetime.now()
    # 拼接key
    key = Prefixs.user_sign_key + date.strftime("%Y:%m:") + user_info['id']
    # 获取天数
    day = date.day
    # 获取最近天数的签到情况 bitmap，返回结果10进制
    number = Redis.bitfield(key, 'u' + str(day), 0)
    # 计算截止今天的连续签到次数
    cnt = 0
    while True:
        if number & 1 == 0:  # 当前没有签到
            break
        cnt += 1  # 签到了
        number >>= 1  # 往前一天
    return restful.success(date=cnt)


